//! \file socket.hpp
//! \brief Purewell Library Socket Header
//! \author Yubin Lim (purewell@gmail.com)
//! \since 2008-01-25

#ifndef __SOCKET_HPP__
#define __SOCKET_HPP__

#include "types.hpp"
#include "file.hpp"
#include "pairfile.hpp"
#include "socketaddress.hpp"

namespace purewell
{

//! \brief Socket.
class PWSocket : public PWFile
{
public:
	//! \brief Initialize socket.
	//! \param[in] family Socket family.
	//! \param[in] socktype Socket type.
	//! \param[in] protocol Protocol type.
	virtual bool initialize(int family, int socktype, int protocol);

	//! \brief Do not use this function.
	//! If you want named socket, use PWSocketAddress object.
	virtual bool initialize(const char*, int, int);

	//! \brief Get socket name.
	//! \param[out] addr Socket address information.
	//! \return Socket address information reference.
	PWSocketAddress& getSocketName(PWSocketAddress& addr) const;

	//! \brief Get peer name.
	//! \param[out] addr Socket address information.
	//! \return Socket address information reference.
	PWSocketAddress& getPeerName(PWSocketAddress& addr) const;

	//! \brief Shutdown.
	//! \param[in] type Shutdown type.
	//! \return On success, true.
	bool shutdown(int type);

	//! \brief Bind.
	//! \param[in] addr Bind information.
	//! \return On success, true.
	bool bind(const PWSocketAddress& addr);

	//! \brief Listen.
	//! \param[in] backlog Backlog size.
	//! \return On success, true.
	bool listen(size_t backlog);

	//! \brief Accept.
	//! \param[out] sock Socket object.
	//! \return On success, true.
	bool accept(PWSocket* sock) const;

	//! \brief Connect.
	//! \param[in] addr Address to connect.
	//! \return On success, true.
	bool connect(const PWSocketAddress& addr);

	//! \brief Receive data from socket.
	//! \param[out] buf Buffer.
	//! \param[in] len Buffer length.
	//! \param[in] flag Flag.
	//! \return On success, operated size or -1.
	ssize_t receive(void* buf, size_t len, int flag);

	//! \brief Receive data from socket.
	//! \param[out] buf Buffer.
	//! \param[in] len Buffer length.
	//! \param[in] flag Flag.
	//! \param[out] paddr Sender information.
	//! \return On success, operated size or -1.
	ssize_t receiveFrom(void* buf, size_t len, int flag,
		PWSocketAddress* paddr);

	//! \brief Send data to socket.
	//! \param[in] buf Buffer.
	//! \param[in] len Buffer length.
	//! \param[in] flag Flag.
	//! \return On success, operated size or -1.
	ssize_t send(const void* buf, size_t len, int flag);

	//! \brief Send data to socket.
	//! \param[in] buf Buffer.
	//! \param[in] len Buffer length.
	//! \param[in] flag Flag.
	//! \param[in] paddr Receiver information.
	//! \return On success, operated size or -1.
	ssize_t sendTo(const void* buf, size_t len, int flag,
		const PWSocketAddress* paddr);

	virtual ssize_t read(void* buf, size_t blen);
	virtual ssize_t write(const void* buf, size_t blen);

public:
	explicit PWSocket();
	virtual ~PWSocket();
};

};//namespace purewell

#endif//!__SOCKET_HPP__

